﻿#ifndef SLTOOL_RESENDLIST_20220126_
#define SLTOOL_RESENDLIST_20220126_

#include <stdint.h>
#include <deque>
#include <map>
#include<string.h>
#include "SLT_timer.h"
#include "SLT_memory.h"
//实现重传触发机制.自身没有线程。需求外面周期调用触发检测
//当有需要发送的对象。通过回掉形式触发
class SLT_resendListUserData
{
public:
	virtual ~SLT_resendListUserData() {}

	SLT_memBuf  m_data;
};
typedef std::shared_ptr< SLT_resendListUserData>  SLT_resendListUserDataSptr;

class SLT_resendItemCL : public SLT_memLeakCheck< SLT_resendItemCL>
{
public:
	uint64_t m_id = 0;
	uint32_t m_type = 0;
	std::string m_strtype;
	int _intervalMs = 1000;
	int _timeOutMs = 5000;

	SLT_resendListUserDataSptr m_userdata;
	SLT_memBuf   m_data;

	SLT_elapseTimer m_startTimer;
	SLT_elapseTimer m_lastTimer;

	bool    m_del = true;  //当超时删除时，根据返回结果确定
};

class SLT_resendList;
class SLT_resendListCB
{
public:
	virtual void SLT_RLResend(SLT_resendList* _plist,SLT_resendItemCL*pitem) = 0;
	virtual void SLT_RLTimeOut(SLT_resendList* _plist,SLT_resendItemCL* pitem) = 0;

};
//重发队列
class SLT_resendList
{
public:
	~SLT_resendList() {
		clear();
	}
	void setCB(SLT_resendListCB* _pcb) { m_pcb = _pcb; }
	void add(uint64_t _id, int _intervalMs, int _timeOutMs, SLT_memBuf& _data)
	{
		SLT_resendItemCL* pitem = new SLT_resendItemCL();
		if (!pitem) {
			return;
		}

		pitem->m_id = _id;
		pitem->m_data = _data;
		pitem->_intervalMs = _intervalMs;
		pitem->_timeOutMs = _timeOutMs;
		pitem->m_lastTimer = pitem->m_startTimer;
		m_list.push_back(pitem);
	}
	void add2(uint64_t _id,uint32_t _type, int _intervalMs, int _timeOutMs, SLT_resendListUserDataSptr _userData)
	{
		SLT_resendItemCL* pitem = new SLT_resendItemCL();
		if (!pitem) {
			return;
		}

		pitem->m_id = _id;
		pitem->m_type = _type;
		pitem->m_userdata = _userData;
		pitem->_intervalMs = _intervalMs;
		pitem->_timeOutMs = _timeOutMs;
		pitem->m_lastTimer = pitem->m_startTimer;
		m_list.push_back(pitem);
	}
	void add3(uint64_t _id,const std::string &_strtype, int _intervalMs, int _timeOutMs, SLT_resendListUserDataSptr _userData)
	{
		SLT_resendItemCL* pitem = new SLT_resendItemCL();
		if (!pitem) {
			return;
		}

		pitem->m_id = _id;
		pitem->m_strtype = _strtype;
		pitem->m_userdata = _userData;
		pitem->_intervalMs = _intervalMs;
		pitem->_timeOutMs = _timeOutMs;
		pitem->m_lastTimer = pitem->m_startTimer;
		m_list.push_back(pitem);
	}
	void del(uint64_t _id)
	{
		if (m_list.empty()) {
			return;
		}
		auto lIter = m_list.begin();
		for (; lIter != m_list.end(); ++lIter) {
			if ((*lIter)->m_id == _id) {
				delete (*lIter);
				m_list.erase(lIter);
				break;
			}
		}
	}
	SLT_resendItemCL* find(uint64_t _id)
	{
		if (m_list.empty()) {
			return nullptr;
		}

		for (auto& item : m_list) {
			if (item->m_id == _id) {
				return item;
			}
		}
		return nullptr;
	}
	void delByType(uint32_t _type)
	{
		if (m_list.empty()) {
			return;
		}
		auto lIter = m_list.begin();
		for (; lIter != m_list.end(); ++lIter) {
			if ((*lIter)->m_type == _type) {
				delete (*lIter);
				m_list.erase(lIter);
				break;
			}
		}
	}
	void delByType(const std::string &_strtype)
	{
		if (m_list.empty()) {
			return;
		}
		auto lIter = m_list.begin();
		for (; lIter != m_list.end(); ++lIter) {
			if ((*lIter)->m_strtype == _strtype) {
				delete (*lIter);
				m_list.erase(lIter);
				break;
			}
		}
	}
	void clear()
	{
		for (auto item : m_list) {
			delete item;
		}
		m_list.clear();
	}
	
	void check()
	{
		if (m_list.empty()) {
			return;
		}

		SLT_elapseTimeType tnow = SLT_elapseTime_now();
		auto lIter = m_list.begin();
		for (; lIter != m_list.end(); ) {
			if (-1 != (*lIter)->_timeOutMs && (*lIter)->m_startTimer.elapseMs(tnow) > (*lIter)->_timeOutMs) {
				//超时删除
				(*lIter)->m_del = true;   //在回掉函数中可以阻止删除，复位，继续超时处理
				m_pcb->SLT_RLTimeOut(this, *lIter);
				if ((*lIter)->m_del) {
					delete (*lIter);
					lIter = m_list.erase(lIter);
				}
				else {
					(*lIter)->m_startTimer.start();
					(*lIter)->m_lastTimer = (*lIter)->m_startTimer;
					++lIter;
				}
				continue;
			}

			if (-1 == (*lIter)->_intervalMs) {
				++lIter;
				continue;
			}

			if ((*lIter)->m_startTimer.elapseMs(tnow) > 10000) {
				//重传超过10s则减速
				if ((*lIter)->_intervalMs < 5000) {
					(*lIter)->_intervalMs = 5000;
				}
			}
			else if ((*lIter)->m_startTimer.elapseMs(tnow) > 5000) {
				//重传超过10s则减速
				if ((*lIter)->_intervalMs < 1000) {
					(*lIter)->_intervalMs = 1000;
				}
			}

			if ((*lIter)->m_lastTimer.elapseMs(tnow) > (*lIter)->_intervalMs) {
				(*lIter)->m_lastTimer.start();
				m_pcb->SLT_RLResend(this, *lIter);
			}
			++lIter;
		}
	}

	std::deque<SLT_resendItemCL*>& getList() { return m_list; }
	std::deque<SLT_resendItemCL*>  m_list;
	SLT_resendListCB *m_pcb;
};

//去重检查
class SLT_recvRepeatCheckUserData
{
public:
	virtual ~SLT_recvRepeatCheckUserData() {}

	SLT_memBuf  m_data;
};
typedef std::shared_ptr< SLT_recvRepeatCheckUserData>  SLT_recvRepeatCheckUserDataSptr;
class SLT_recvRepeatCheck
{
	class _rrc_item : public SLT_memLeakCheck< _rrc_item>
	{
	public:
		uint64_t index;
		SLT_elapseTimer  start;

		SLT_recvRepeatCheckUserDataSptr m_userdata;
	};
public:
	int checkRecv(uint64_t _index, SLT_recvRepeatCheckUserDataSptr& _userdata)
	{
		auto mIter = m_recvMap.find(_index);
		if (mIter == m_recvMap.end()) {
			return 0;
		}
		mIter->second.start.start();
		_userdata = mIter->second.m_userdata;
		return -1;
	}
	int save(uint64_t _index, const char* _pdata, int _pdlen) 
	{
		SLT_recvRepeatCheckUserDataSptr ud = std::make_shared<SLT_recvRepeatCheckUserData>();
		ud->m_data.add(_pdata, _pdlen);
		_rrc_item item;
		item.index = _index;
		item.m_userdata = ud;
		m_recvMap.insert(std::make_pair(_index, item));
		return 0;
	}
	int save2(uint64_t _index,const SLT_recvRepeatCheckUserDataSptr &_userdata) 
	{
		_rrc_item item;
		item.index = _index;
		item.m_userdata = _userdata;
		m_recvMap.insert(std::make_pair(_index, item));
		return 0;
	}
	void clear() {
		m_recvMap.clear();
	}
	void checkState()
	{
		if (m_checkTime.elapseMs() > 30000) {
			m_checkTime.start();
			auto iIter = m_recvMap.begin();
			for (; iIter != m_recvMap.end();) {
				if (iIter->second.start.elapseMs() > 60000) {
					m_recvMap.erase(iIter++);
				}
				else {
					++iIter;
				}
			}
		}
	}

	SLT_elapseTimer   m_checkTime;
	std::map<uint64_t, _rrc_item> m_recvMap;
};

#endif